//
//  UploadController.m
//  ObjectiveYouTube
//
//  Created by Tristan O'Tierney on 1/11/08.
//  Copyright 2008 Tristan O'Tierney. All rights reserved.
//

#import "UploadController.h"
#import "Keychain.h"
#import "DemoKey.h"
#import <ObjectiveYouTube/ObjectiveYouTube.h>

#define DEBUG 1

static NSString *kYouTubeSource = @"ObjectiveYouTubeUploader";
static NSString *kLastUserLoginKey = @"LastUserLogin";
static NSString *kYouTubeService = @"YouTubeService";

@interface UploadController (Private)
- (void)_setLoginState:(LoginState)state;
- (void)_stopUpload;
- (void)_loadCategories;
@end

@implementation UploadController
#pragma mark -
#pragma mark UI Actions
#pragma mark -

- (id)init {
	if ((self = [super init])) {
		_authenticator = [[OYAuthenticator alloc] initWithDelegate:self
														  clientID:kClientID
													  developerKey:kDeveloperKey
															source:kYouTubeSource];
		_uploader = [[OYUploader alloc] initWithDelegate:self authenticator:_authenticator];
		_categories = [[OYCategoriesController alloc] initWithDelegate:self];
		_loginState = LoginStateLoggedOut;		
	}
	
	return self;
}

- (void)dealloc {
	[_uploader release];
	[_authenticator release];
	
	[super dealloc];
}

#pragma mark -
#pragma mark UI Actions
#pragma mark -

- (IBAction)loginPressed:(id)sender {
	if (DEBUG) NSLog(@"loginPressed:");
	
	switch (_loginState) {
		case LoginStateLoggedOut:
			if (DEBUG) NSLog(@"starting login");
			[self _setLoginState:LoginStateProcessing];
			[_authenticator loginAsUser:[userNameField stringValue] withPassword:[passwordField stringValue]];
			break;
			
		case LoginStateProcessing:
			if (DEBUG) NSLog(@"cancelling login");
			[self _setLoginState:LoginStateLoggedOut];
			[_authenticator cancelLogin];
			break;
			
		case LoginStateLoggedIn:
			if (DEBUG) NSLog(@"logging out");
			[self _setLoginState:LoginStateLoggedOut];
			[_authenticator logout];
			break;
	}
}

- (IBAction)browsePressed:(id)sender {
	if (DEBUG) NSLog(@"browsePressed:");
	
	NSOpenPanel *openPanel = [NSOpenPanel openPanel];
	NSArray *types = [NSArray arrayWithObjects:@"mov", @"mp4", @"m4v", @"avi", @"divx", @"wmv", @"asf", @"flv", @"mkv", @"mpg", @"mpeg", @"ogm", @"rm", @"dat", @"3gp", nil];
	
	[openPanel setCanChooseDirectories:NO];
	[openPanel setAllowsMultipleSelection:NO];
	[openPanel setPrompt:NSLocalizedString(@"Choose Movie", @"Choose Movie")];
	
	[openPanel beginSheetForDirectory:nil
								 file:[filePathField stringValue]
								types:types
					   modalForWindow:window
						modalDelegate:self
					   didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
						  contextInfo:nil];
}

- (IBAction)uploadPressed:(id)sender {
	if (DEBUG) NSLog(@"uploadPressed:");
	
	if ([[uploadButton title] isEqualToString:@"Upload"]) {
		[uploadButton setTitle:@"Cancel"];
		[uploadProgress setHidden:NO];	
		[uploadProgress setMaxValue:0.0f];
		[uploadProgress setIndeterminate:YES];
		[uploadProgress startAnimation:self];
		
		[_uploader uploadFile:[filePathField stringValue]
					withTitle:[titleField stringValue]
				  description:[descriptionField stringValue]
					 category:(OYCategory *)[[categoryPopUp selectedItem] representedObject]
						 tags:(NSArray *)[tagsField objectValue]
					  privacy:([privacyButton state] == NSOnState ? kOYPublicPrivacy : kOYPrivatePrivacy)
						 date:[NSDate date]
				  contextInfo:NULL];
	} else {
		[_uploader cancelUpload];
		
		[self _stopUpload];
	}
}

#pragma mark -
#pragma mark Callbacks
#pragma mark -

- (void)awakeFromNib {
	if (DEBUG) NSLog(@"awakeFromNib");
	
	// Uncomment these three lines if you want to dynamically
	// load the categories instead of load the static file
	/*
	// reload the available category choices
	[categoryProgress setHidden:NO];
	[categoryProgress startAnimation:nil];
	[_categories refreshCategories];
	*/
	[self _loadCategories];
	
	// load the username/pw
	Keychain *keychain = [Keychain defaultKeychain];
	NSString *lastLogin = [[NSUserDefaults standardUserDefaults] stringForKey:kLastUserLoginKey];
	
	if ([lastLogin length]) {
		NSString *password = [keychain passwordForGenericService:kYouTubeService forAccount:lastLogin];
		
		if ([password length]) {
			[userNameField setStringValue:lastLogin];
			[passwordField setStringValue:password];
			[self loginPressed:nil];
		}
	} else {
		[self _setLoginState:LoginStateLoggedOut];
	}
}

- (void)windowWillClose:(NSNotification *)notification {
	[NSApp terminate:nil];
}

- (void)openPanelDidEnd:(NSOpenPanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo {
	if (DEBUG) NSLog(@"browse for file ended");
	if (returnCode != NSOKButton) {
		return;
	}
	
	NSString *fileName = [[panel filenames] lastObject];
	if (DEBUG) NSLog(@"Choosen file: %@", fileName);
	
	[filePathField setStringValue:fileName];
}

- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector {
	if (commandSelector == @selector(insertNewline:)) {
		if ([[userNameField stringValue] length] && [[passwordField stringValue] length]) {
			[self loginPressed:nil];
		} else if ([[userNameField stringValue] length]) {
			[window makeFirstResponder:passwordField];
		} else {
			[window makeFirstResponder:userNameField];
		}		
    }
	
	return NO;
}

#pragma mark -
#pragma mark Uploader Callbacks
#pragma mark -

- (void)authenticator:(OYAuthenticator *)auth succededWithToken:(NSString *)token {
	if (DEBUG) NSLog(@"UploadController succededWithToken: %@", token);
	[self _setLoginState:LoginStateLoggedIn];
	[window makeFirstResponder:browseButton];
}

- (void)authenticator:(OYAuthenticator *)auth failedWithError:(NSError *)error {
	[self _setLoginState:LoginStateLoggedOut];

	NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Login Error", @"Login Error")
									 defaultButton:NSLocalizedString(@"OK", @"OK")
								   alternateButton:nil
									   otherButton:nil
						 informativeTextWithFormat:NSLocalizedString(@"Incorrect username or password", @"Incorrect username or password")];
	[alert beginSheetModalForWindow:window
					  modalDelegate:nil
					 didEndSelector:nil
						contextInfo:nil];
	
	[window makeFirstResponder:passwordField];
}

- (void)uploader:(OYUploader *)uploader failedUploadWithError:(NSError *)error contextInfo:(void *)info {
	NSLog(@"upload error: %@", error);
	[self _stopUpload];

	NSAlert *alert = [NSAlert alertWithError:error];
	[alert beginSheetModalForWindow:window
					  modalDelegate:nil
					 didEndSelector:nil
						contextInfo:nil];
}

- (void)uploader:(OYUploader *)uploader succededWithResponse:(OYVideoResponse *)response contextInfo:(void *)info {
	if (DEBUG) NSLog(@"youtube url: %@", [response publicURL]);
	
	NSAlert *alert = [NSAlert alertWithMessageText:@"Upload Succeded"
									 defaultButton:@"View Video"
								   alternateButton:@"Close"
									   otherButton:nil
						 informativeTextWithFormat:@"Your video has successfully uploaded"];
	
	[alert beginSheetModalForWindow:window
					  modalDelegate:self
					 didEndSelector:@selector(successDidFinish:returnCode:contextInfo:)
						contextInfo:response];
	
	[self _stopUpload];
}

- (void)successDidFinish:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo {
	if (returnCode == NSAlertDefaultReturn) {
		OYVideoResponse *videoResponse = (OYVideoResponse *)contextInfo;
		NSURL *editURL = [videoResponse editURL];
		if (DEBUG) NSLog(@"edit url response: %@", editURL);
		
		[[NSWorkspace sharedWorkspace] openURL:editURL];
	}
}

- (void)uploader:(OYUploader *)uploader progress:(size_t)bytesSent total:(size_t)totalLength contextInfo:(void *)info {
	if ([uploadProgress maxValue] != totalLength) {
		[uploadProgress setIndeterminate:NO];
		[uploadProgress stopAnimation:self];
		[uploadProgress setMaxValue:totalLength];
	}
	
	[uploadProgress setDoubleValue:bytesSent];
}

- (void)categories:(OYCategoriesController *)categories refreshedWithCategories:(NSArray *)categoriesArray {
	if (DEBUG) NSLog(@"Uploader refreshedWithCategories: %@", categoriesArray);
	[categoryProgress stopAnimation:nil];
	[categoryProgress setHidden:YES];
	
	[self _loadCategories];
}

- (void)categories:(OYCategoriesController *)categories refreshFailedWithError:(NSError *)error {
	NSLog(@"Uploader refreshFailedWithError: %@", error);
	[categoryProgress stopAnimation:nil];
	[categoryProgress setHidden:YES];
}

#pragma mark -
#pragma mark Private Methods
#pragma mark -

- (void)_setLoginState:(LoginState)state {
	_loginState = state;
	
	switch (_loginState) {
		case LoginStateLoggedIn: {
			NSString *username = [userNameField stringValue];

			[loginButton setTitle:NSLocalizedString(@"Logout", @"Logout")];
			[loginProgress setHidden:YES];
			[loginProgress stopAnimation:nil];
			[userNameField setEnabled:NO];
			[passwordField setEnabled:NO];
			[uploadButton setEnabled:YES];
			
			[[NSUserDefaults standardUserDefaults] setObject:username forKey:kLastUserLoginKey];
			[[Keychain defaultKeychain] addGenericPassword:[passwordField stringValue]
												 onService:kYouTubeService
												forAccount:username
										   replaceExisting:YES];
			break;			
		}
			
		case LoginStateProcessing:
			[loginButton setTitle:NSLocalizedString(@"Cancel", @"Cancel")];
			[loginProgress setHidden:NO];
			[loginProgress startAnimation:nil];
			[userNameField setEnabled:NO];
			[passwordField setEnabled:NO];
			[uploadButton setEnabled:NO];
			break;
		
		case LoginStateLoggedOut: {
			NSString *username = [[NSUserDefaults standardUserDefaults] stringForKey:kLastUserLoginKey];
			
			[loginButton setTitle:NSLocalizedString(@"Login", @"Login")];
			[loginProgress setHidden:YES];
			[loginProgress stopAnimation:nil];
			[userNameField setEnabled:YES];
			[window makeFirstResponder:userNameField];
			[passwordField setEnabled:YES];
			[uploadButton setEnabled:NO];
			
			if ([username length]) {
				[[Keychain defaultKeychain] deletePasswordForGenericService:kYouTubeService forAccount:username];
			}
			[[NSUserDefaults standardUserDefaults] removeObjectForKey:kLastUserLoginKey];
			break;
		}
	}
}

- (void)_stopUpload {
	// set upload button title
	[uploadButton setTitle:@"Upload"];
	
	// set upload progress bar visible
	[uploadProgress setHidden:YES];
	[uploadProgress setMaxValue:0.0f];
}

- (void)_loadCategories {
	NSArray *categoriesArray = [_categories categories];
	NSEnumerator *en = [categoriesArray objectEnumerator];
	OYCategory *category = nil;
	
	[categoryPopUp removeAllItems];
	
	while ((category = [en nextObject]) != nil) {
		[categoryPopUp addItemWithTitle:[category label]];
		[[categoryPopUp lastItem] setRepresentedObject:category];
	}
}
@end
